﻿#include "YTools.h"

#include <sstream>

using namespace std;

extern "C"
{
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
}


//自定义线程sleep毫秒数（更为准确）
void MSleep(unsigned int ms)
{
	auto beg = clock();
	for (int i = 0; i < ms; i++)
	{
		this_thread::sleep_for(1ms);
		if ((clock() - beg) / (CLOCKS_PER_SEC / 1000) >= ms)
			break;
	}
}

//当前时间，单位是毫秒
long long NowMs()
{
	return clock() / (CLOCKS_PER_SEC / 1000);
}

//手动释放一个AVFrame
void YFreeFrame(AVFrame** frame)
{
	if (!frame || !(*frame))return;
	av_frame_free(frame);
}

long long YRescale(long long pts,
	AVRational* src_time_base,
	AVRational* des_time_base)
{
	return av_rescale_q(pts, *src_time_base, *des_time_base);
}


//启动线程
void YThread::Start()
{
	std::unique_lock<std::mutex> lock(mut_);
	static int i = 0;
	i++;
	index_ = i;
	isExit_ = false;
	//启动线程
	th_ = std::thread(&YThread::Working, this);
	stringstream ss;
	ss << "YThread::Start()" << index_;
	LOGINFO(ss.str());
}

//等待线程退出
void YThread::Wait()
{
	stringstream ss;
	if (th_.joinable()) //判断子线程是否可以等待
		th_.join();     //等待子线程退出
	ss.str("");
	ss << "XThread::Stop() end" << index_;
	LOGINFO(ss.str());
}

//设置线程退出标志
void YThread::Exit()
{
	stringstream ss;
	ss << "XThread::Stop() begin" << index_;
	LOGINFO(ss.str());
	isExit_ = true;
}


//停止线程（设置退出标志，等待线程退出）
void YThread::Stop()
{
	Exit();
	Wait();
}


//创建对象
YAVParameters* YAVParameters::Create()
{
	return new YAVParameters();
}

YAVParameters::~YAVParameters()
{
	if (para)
	{
		avcodec_parameters_free(&para);
	}
	if (time_base)
	{
		delete time_base;
		time_base = nullptr;
	}
}

//私有是禁止创建栈中对象
YAVParameters::YAVParameters()
{
	para = avcodec_parameters_alloc();
	time_base = new AVRational();
}

AVPacket* YAVPacketList::Pop()
{
	unique_lock<mutex> lock(mux_);
	if (pkts_.empty())return nullptr;
	auto pkt = pkts_.front();
	pkts_.pop_front();
	return pkt;
}

int YAVPacketList::Size()
{
	unique_lock<mutex> lock(mux_);
	return pkts_.size();
}

void YAVPacketList::Clear()
{
	unique_lock<mutex> lock(mux_);
	while (!pkts_.empty())
	{
		av_packet_free(&pkts_.front());
		pkts_.pop_front();
	}
}

void YAVPacketList::Push(AVPacket* pkt)
{
	unique_lock<mutex> lock(mux_);
	//生成新的AVPacket 对象 引用计数+1;
	auto p = av_packet_alloc();
	av_packet_ref(p, pkt);//引用计数 减少数据复制，线程安全
	pkts_.push_back(p);

	//超出最大空间，清理数据，到关键帧位置
	if (pkts_.size() > max_packets_)
	{
		//处理第一帧
		if (pkts_.front()->flags & AV_PKT_FLAG_KEY)//关键帧
		{
			av_packet_free(&pkts_.front());//清理
			pkts_.pop_front();  //出队
			return;
		}
		//清理所有非关键帧之前的数据
		while (!pkts_.empty())
		{
			if (pkts_.front()->flags & AV_PKT_FLAG_KEY)//关键帧
			{
				return;
			}
			av_packet_free(&pkts_.front());//清理
			pkts_.pop_front();  //出队
		}
	}

}


AVFrame* YAVFrameList::Pop()
{
	unique_lock<mutex> lock(mux_);
	if (frames_.empty())return nullptr;
	auto frame = frames_.front();
	frames_.pop_front();
	return frame;
}

void YAVFrameList::Push(AVFrame* frame)
{
	unique_lock<mutex> lock(mux_);
	frames_.push_back(frame);
}

int YAVFrameList::Size()
{
	unique_lock<mutex> lock(mux_);
	return frames_.size();
}

void YAVFrameList::Clear()
{
	unique_lock<mutex> lock(mux_);
	while (!frames_.empty())
	{
		av_frame_free(&frames_.front());
		frames_.pop_front();
	}
}
